#include "../include/head.h"
int client_upload(int fd_socket, char *filename) {
    Truck_t node;
    off_t filesize;

    // 1. 接收客户端文件总大小
    recv(fd_socket, &node.truck_len, sizeof(node.truck_len), MSG_WAITALL);
    recv(fd_socket, node.truck_data, node.truck_len, MSG_WAITALL);
    memcpy(&filesize, node.truck_data, node.truck_len);
    printf("server: client upload total size = %ld\n", filesize);

    // 2. 创建临时文件名
    char partfile[256];
    snprintf(partfile, sizeof(partfile), "%s.part", filename);
    printf("partfile  = %s\n",partfile);
    off_t offset = 0;
    int fd;

    // 3. 判断是否存在 .part 文件
    struct stat st;
    if (stat(partfile, &st) == 0) {
        // 3.1 存在 .part 文件，询问客户端是否继续
        char choice = 0; // 1: 继续传输 0: 重新传输
        send(fd_socket, "EXIST", 5, 0);
        printf("SERVER  get 01\n");
        recv(fd_socket, &choice, sizeof(choice), MSG_WAITALL);

        if (choice == 1) {
            // 继续传输，从断点开始
            offset = st.st_size;
            fd = open(partfile, O_RDWR, 0666);
            lseek(fd, offset, SEEK_SET);
        } else {
            // 删除临时文件，重新传输
            unlink(partfile);
            fd = open(partfile, O_RDWR | O_CREAT | O_TRUNC, 0666);
            offset = 0;
        }
    } else {
        send(fd_socket,"succs",5,0);
        // 不存在，创建临时文件
        fd = open(partfile, O_RDWR | O_CREAT | O_TRUNC, 0666);
        offset = 0;
    }

    // 4. 告诉客户端从 offset 开始传输
    send(fd_socket, &offset, sizeof(offset), 0);

    // 5. 开始接收文件数据
    off_t cursize = offset;
    off_t lastsize = offset;
    off_t slice = filesize / 100;

    while (1) {
        bzero(node.truck_data, sizeof(node.truck_data));
        recv(fd_socket, &node.truck_len, sizeof(node.truck_len), MSG_WAITALL);

        if (node.truck_len == 0) break; // 文件传输完成

        ssize_t sret = recv(fd_socket, node.truck_data, node.truck_len, MSG_WAITALL);
        if (sret <= 0){
            printf("sret == %ld\n",sret);
            break;
        }


        write(fd, node.truck_data, sret);
        cursize += sret;

        if (cursize - lastsize >= slice) {
            printf("%5.2lf%%\r", 100.0 * cursize / filesize);
            fflush(stdout);
            lastsize = cursize;
        }
    }

    close(fd);

    // 6. 文件传输完成，将 .part 文件重命名为正式文件
    if(cursize == filesize){
        
        rename(partfile, filename);
    }
    printf("\nserver: upload finished\n");

    return 0;
}

//实现上传
int upload(int fd_socket,char *filename){
    //创建TLV协议相关结构体
    Truck_t node;
    //int flag = -1;
   // recv(fd_socket,&flag,sizeof(int),0);
    //if(flag == 0){
      //  return -1;
    //}
    
    //用于接收文件大小
    off_t filesize;
    recv(fd_socket,&node.truck_len,sizeof(node.truck_len),MSG_WAITALL);
    printf("server : client upload file bianjie len = %d\n",node.truck_len);
    recv(fd_socket,node.truck_data,node.truck_len,MSG_WAITALL);
    memcpy(&filesize,node.truck_data,node.truck_len); //err  改正√
    
    //用于比较当前所传文件大小与总文件大小
    off_t cursize = 0;
    off_t lastsize = 0;
    off_t slice = filesize/100;
    
    //打开文件的传输通道
    int fd = open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
    while(1){
        //清空结构体内的缓存
        bzero(node.truck_data,sizeof(node.truck_data));
        recv(fd_socket,&node.truck_len,sizeof(node.truck_len),MSG_WAITALL);
        //当传输火车头长度为0时，证明文件传输完成
        if(node.truck_len == 0){
            break;
        }
        ssize_t sret = recv(fd_socket,node.truck_data,node.truck_len,MSG_WAITALL);
        printf("server: client uploading data len = %ld\n ",sret);
        write(fd,node.truck_data,node.truck_len);
        
        //实时更新当前已传输文件大小
        cursize += node.truck_len;
        //打印文件传输的进度
        if(cursize - lastsize >= slice){
            printf("%5.2lf%%\r",100.0*cursize/filesize);
            fflush(stdout);
            lastsize = cursize;
        }
    }
    close(fd);
    return 0;
}

//实现下载
int download(int fd_socket,char *filename){
    printf("file name = %s\n",filename);
    //判断文件类型是否正确
    //DIR*dirp = opendir("./");
    //struct dirent *dir_cur;
    //int flag = -1;
    //
    //while((dir_cur = readdir(dirp))!=NULL){
    //    if(!strcmp(dir_cur->d_name,filename)){
    //        if(S_ISREG(dir_cur->d_type)){
    //            //如果是普通文件，传输
    //            flag = 1;
    //            send(fd_socket,&flag,sizeof(int),0);
    //            printf("server send\n");
    //        }else{
    //            //如果不是普通文件，不传
    //            flag = 0;
    //            send(fd_socket,&flag,sizeof(int),0);
    //            printf("server send\n");
    //        }
    //        break;
    //    }
    //}
    //closedir(dirp);
    //if(flag == 0){
    //    //不是普通文件，退出
    //    return -1;
    //}

    Truck_t node;
    
    int fd = open(filename,O_RDWR);
    //设置一个结构体记录获取文件大小
    struct stat statbuf;
    fstat(fd,&statbuf);
    off_t filesize = statbuf.st_size;
    printf("filesize===%lu\n",filesize);
    node.truck_len = sizeof(filesize);
    printf("train.len = %d\n",node.truck_len);
    //将文件大小通过TLV协议传输过去
    memcpy(node.truck_data,&filesize,node.truck_len);

    send(fd_socket,&node.truck_len,sizeof(int),MSG_NOSIGNAL);
    printf("server send\n");
    printf("send node bianjie len =%d\n",node.truck_len);
    send(fd_socket,node.truck_data,node.truck_len,MSG_NOSIGNAL);
    printf("server send\n");
    printf("send node daxiao data =%s\n",node.truck_data);
    //判断文件大小，文件大于100MB使用mmap传输
    if(filesize > MAXFILESIZE){
        //固定文件大小
        ftruncate(fd,filesize);
        char *p = (char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        off_t offset = 0;
        while(offset < filesize){
            if(filesize - offset > 4096){
                node.truck_len = 4096;
            }else{
                node.truck_len = filesize - offset;
            }
            send(fd_socket,&node.truck_len,sizeof(node.truck_len),MSG_NOSIGNAL);
            send(fd_socket,p + offset,node.truck_len,MSG_NOSIGNAL);
            offset += node.truck_len;
        }
        munmap(p,filesize);
    }else{
        //当文件大小不足100MB时，TLV传输
        while(1){
            bzero(node.truck_data,sizeof(node.truck_data));
            ssize_t sret = read(fd,node.truck_data,sizeof(node.truck_data));
            if(sret == 0){
                printf("read over\n");
                break;
            }
            node.truck_len = sret;
            send(fd_socket,&node.truck_len,sizeof(node.truck_len),MSG_NOSIGNAL);
            printf("server send\n");
            send(fd_socket,node.truck_data,node.truck_len,MSG_NOSIGNAL);
            printf("server send\n");
        }
    }
    node.truck_len = 0;
    send(fd_socket,&node.truck_len,sizeof(node.truck_len),MSG_NOSIGNAL);
    printf("server send 0\n");
    close(fd);
    return 0;
}

